package com.weiqiao.api.until;

import com.google.gson.Gson;
import com.mingsoft.util.StringUtil;
import com.mongodb.client.model.Filters;
import com.weiqiao.api.domain.AppUserApiEntity;
import com.weiqiao.api.domain.dto.TeamApiEntityDTO;
import com.weiqiao.api.domain.dto.wx.*;
import com.weiqiao.api.repository.IAppuserApiRepository;
import com.weiqiao.api.repository.ITeamApiRepository;
import com.weiqiao.api.service.IAppUserApiService;
import com.weiqiao.api.until.config.WXConfig;
import com.weiqiao.modules.basic.base.constant.entity.ResourcesEnum;
import com.weiqiao.utils.DateUtils;
import com.weiqiao.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import redis.clients.jedis.Jedis;

/**
 * 微信工具类
 */
@Slf4j
@Component
public class WxUtils {
    @Autowired
    RestTemplate restTemplate;

    @Autowired
    private IAppUserApiService userService;

    @Autowired
    private IAppuserApiRepository appuserApiRepository;

    @Autowired
    private ITeamApiRepository teamApiRepository;

    /**
     * 当redis中不存在时 手动调用
     * tocken和ticket由定时器刷新
     */
    public void getToken() {
        AccessToken accessToken = getWxAccessToken();
        String accesstoken = accessToken.getAccess_token();
        // 根据令牌获取调用微信的票据jsapi_ticket
        WxTicket wxTicket = getTicket();
        String ticket = wxTicket.getTicket();

        // 将获取的Token和ticket存入redis
        Jedis jedis = RedisUtil.getJedis();
        jedis.set("wchartProof:accesstoken", accesstoken);
        jedis.set("wchartProof:ticket", ticket);
    }

    /**
     * 绑定用户上下级
     *
     * @param user_id 用户id
     * @param param   参数信息
     * @return
     */
    public ResponseUserInfo bindingUserInfo(String user_id, String param, String phone) {
        ResponseUserInfo responseUserInfo = new ResponseUserInfo();
        if (!StringUtil.isInteger(user_id)) return responseUserInfo;
        Integer company_id = WXConfig.COMPANYID;
        String[] params = param.split(",");
        boolean is_my_login = params.length == 1;

        String qrcode_type = is_my_login ? "3" : params[0]; // 二维码类型
        Integer recommend_id = (!is_my_login && StringUtil.isInteger(params[1])) ? Integer.parseInt(params[1]) : 0; // 邀请人id
        String team_id = (!is_my_login && StringUtil.isLong(params[2])) ? params[2] : ""; //团队id

        // 当前用户信息
        Bson filter = new Document("user_id", Integer.parseInt(user_id));
        AppUserApiEntity user = userService.getUser(company_id, filter);
        // 如果没有查询到当前用户信息，则直接返回
        if (user == null) return responseUserInfo;

        // 修改手机号
        if (!StringUtil.isBlank(phone)) {
            // 通过手机号查询后台是否有创建过该手机号的账号
            AppUserApiEntity userByPhone = userService.getUser(company_id, new Document("phone", phone));
            if (StringUtil.isBlank(userByPhone)) {
                user.setPhone(phone);
            } else {
                // 判断该账号是否有被合并过
                if (StringUtil.isBlank(userByPhone.getUnionid())) {
                    // 合并账号
                    user.setMember_type(userByPhone.getMember_type());
                    user.setActive_team(userByPhone.getActive_team());
                    user.setUser_name(userByPhone.getUser_name());
                    user.setPhone(userByPhone.getPhone());
                    // 删除合并前的账号
                    appuserApiRepository.delUser(company_id, new Document("user_id", userByPhone.getUser_id()));
                    // 修改当前用户的下级邀请人id
                    appuserApiRepository.updateAppUser(company_id,
                            new Document("recommend_id", userByPhone.getUser_id()),
                            new Document("recommend_id", user.getUser_id()),
                            true
                    );
                } else {
                    responseUserInfo.setMessage(ResourcesEnum.GROUP_31.getMessage());
                    return responseUserInfo;
                }
            }
        }

        // 如果有推荐人信息且当前用户没有邀请人，绑定上级信息(上级不能是自己，且等级比自己高)
        AppUserApiEntity recommendUser = null;
        if (user.getRecommend_id() == 0 && recommend_id != 0 && recommend_id != user.getRecommend_id()) {
            recommendUser = userService.getUser(company_id, new Document("user_id", recommend_id));
            if (!StringUtil.isBlank(recommendUser)) {
                // 绑定上下级关系
                boolean bool = setUserRecommmend(company_id, recommendUser, user);
                if (!bool) {
                    responseUserInfo.setMessage("邀请人等级必须大于自己等级！");
                    return responseUserInfo;
                }
            } else {
                responseUserInfo.setMessage("邀请人id不存在！");
                return responseUserInfo;
            }
        }
        // 当前用户等级关系
        setUserEntity(qrcode_type, team_id, recommendUser, user);
        userService.updateUser(company_id, user);
        responseUserInfo.setUser(user);
        return responseUserInfo;
    }

    /**
     * 通过微信授权code ,获取微信用户信息
     * 二维码类型：0：商品分享 1：招募合伙人 2：团码
     *
     * @param code  微信返回的Code信息
     * @param param 其他参数  二维码类型,邀请人id,团队id
     * @return
     */
    public ResponseUserInfo getWeixinUserInfo(String code, String param) {
        Integer company_id = WXConfig.COMPANYID;
        Jedis jedis = RedisUtil.getJedis();
        String[] params = param.split(",");
        boolean is_my_login = params.length == 1;

        String qrcode_type = is_my_login ? "3" : params[0]; // 二维码类型
        Integer recommend_id = (!is_my_login && StringUtil.isInteger(params[1])) ? Integer.parseInt(params[1]) : 0; // 邀请人id
        String team_id = (!is_my_login && StringUtil.isLong(params[2])) ? params[2] : ""; //团队id

        boolean is_add = false;
        ResponseUserInfo responseUserInfo = new ResponseUserInfo();
        if (!StringUtil.isBlank(code)) {
            WxRefreshToken wxRefreshToken = getAccessToken(code);
            // 获取用户信息
            WxUserInfo wxUserInfo = getUserInfo(wxRefreshToken.getAccess_token(), wxRefreshToken.getOpenid());
            AppUserApiEntity user = userService.getUser(company_id, wxUserInfo.getUnionid());
            // 未获取到用户则新建
            if (user == null) {
                is_add = true;
                user = new AppUserApiEntity();
                user.setUser_id(userService.getAppUserMaxId(company_id) + 1);
                user.setIcon_url(wxUserInfo.getHeadimgurl());
                user.setCompany_id(company_id);
                user.setUnionid(wxUserInfo.getUnionid());
                user.setOpenid(wxUserInfo.getOpenid());
                user.setSalt(RandomUtils.generateString(6));
                user.setCreate_time(DateUtils.currentTimeMillis());
            }
            user.setRefreshToken(wxRefreshToken.getRefresh_token());
            user.setNickname(wxUserInfo.getNickname());

            AppUserApiEntity recommendUser = null;
            // 如果有推荐人信息且当前用户没有邀请人，绑定上级信息(上级不能是自己，且等级比自己高)
            if (user.getRecommend_id() == 0 && recommend_id != 0 && recommend_id != user.getRecommend_id()) {
                recommendUser = userService.getUser(company_id, new Document("user_id", recommend_id));
                if (!StringUtil.isBlank(recommendUser)) {
                    setUserRecommmend(company_id, recommendUser, user);
                }
            }
            // 设置用户的角色等级以及团队信息
            setUserEntity(qrcode_type, team_id, recommendUser, user);

            // 判断微信id
            if (wxUserInfo.getOpenid() != null) {
                AppUserApiEntity userInfo = user;
                // 存储用户信息
                if (is_add) {
                    userInfo = userService.addUser(company_id, user);
                } else {
                    userService.updateUser(company_id, user);
                }
                responseUserInfo.setUser(userInfo);
                responseUserInfo.setToken(wxRefreshToken);
                responseUserInfo.setTicket(jedis.get("wchartProof:ticket"));
                responseUserInfo.setUserInfo(wxUserInfo);
            }
        }
        System.out.println("最终返回用户信息：" + responseUserInfo);
        return responseUserInfo;
    }

    /**
     * 判断绑定上级邀请人的信息
     *
     * @param company_id     公司id
     * @param recommend_user 邀请人信息
     * @param user           当前用户
     */
    private boolean setUserRecommmend(Integer company_id, AppUserApiEntity recommend_user, AppUserApiEntity user) {
        // 判断当前客户等级，如果是客户需要找上级分销员，如果没有则为空
        if (recommend_user.getMember_type() > 0 && recommend_user.getMember_type() > user.getMember_type()) {
            user.setRecommend_id(recommend_user.getUser_id());
            user.setRecommend_date(DateUtils.currentTimeMillis());
            return true;
        }
        if (recommend_user.getMember_type() == 0) {
            AppUserApiEntity recommendUser = userService.getUser(company_id, new Document("user_id", recommend_user.getRecommend_id()));
            if (!StringUtil.isBlank(recommendUser)) {
                user.setRecommend_id(recommendUser.getUser_id());
                user.setRecommend_date(DateUtils.currentTimeMillis());
                return true;
            }
        }
        return false;
    }

    /**
     * 获取用户refreshToken和AccessToken
     *
     * @param code
     * @return
     */
    public WxRefreshToken getAccessToken(String code) {
        String url = WXConfig.ACCESSTOKEN + WXConfig.APPID + "&secret=" + WXConfig.APPSCRECT + "&code=" + code + "&grant_type=authorization_code";
        String result = restTemplate.getForObject(url, String.class);
        Gson gson = new Gson();
        WxRefreshToken wxRefreshToken = gson.fromJson(result, WxRefreshToken.class);
        System.out.println("通过code获取用户AccessToken：" + wxRefreshToken);
        return wxRefreshToken;
    }

    /**
     * 获取用户信息
     *
     * @param accessToken
     * @param openId
     * @return
     */
    public WxUserInfo getUserInfo(String accessToken, String openId) {
        //最终返回用户信息
        String url = WXConfig.USERINFO + accessToken + "&openid=" + openId + "&lang=zh_CN";
        String result = restTemplate.getForObject(url, String.class);
        Gson gson = new Gson();
        WxUserInfo userInfo = gson.fromJson(result, WxUserInfo.class);
        System.out.println("获取微信用户信息：" + userInfo);
        return userInfo;
    }

    /**
     * 根据AccessToken获取ticket
     *
     * @return
     */
    public WxTicket getTicket() {
        Jedis jedis = RedisUtil.getJedis();
        String url = WXConfig.TICKET + jedis.get("wchartProof:accesstoken") + "&type=jsapi";
        String result = restTemplate.getForObject(url, String.class);
        Gson gson = new Gson();
        WxTicket wxTicket = gson.fromJson(result, WxTicket.class);
        return wxTicket;
    }


    /**
     * 获取微信客户端AccessToken
     *
     * @return
     */
    public AccessToken getWxAccessToken() {
        String url = WXConfig.CLIENTCREDENTIAL + WXConfig.APPID + "&secret=" + WXConfig.APPSCRECT;
        String result = restTemplate.getForObject(url, String.class);
        Gson gson = new Gson();
        AccessToken accessToken = gson.fromJson(result, AccessToken.class);
        return accessToken;
    }

    /**
     * refreshToken刷新Token
     *
     * @param refreshToken
     * @return
     */
    public WxRefreshToken getRefreshToken(String refreshToken) {
        if (StringUtil.isBlank(refreshToken)) {
            return null;
        }
        String url = WXConfig.REFRESHTOKEN + WXConfig.APPID + "&grant_type=refresh_token&refresh_token=" + refreshToken;
        String result = restTemplate.getForObject(url, String.class);
        Gson gson = new Gson();
        WxRefreshToken wxRefreshToken = gson.fromJson(result, WxRefreshToken.class);
        return wxRefreshToken;
    }


    /**
     * 根据条件设置用户的等级以及团队信息
     *
     * @param qrcode_type   二维码类型
     * @param team_id       团队id
     * @param recommendUser 邀请人信息
     * @param user          当前用户信息
     */
    private void setUserEntity(
            String qrcode_type, String team_id,
            AppUserApiEntity recommendUser, AppUserApiEntity user
    ) {
        /**
         * 判断二维码类型
         * 会员类型  0:客户  1：分销员  2：团长  3：省长
         * 需求解析：
         *  商品二维码：
         *      当分享人是省长时，扫码者进来之后客户等级为客户
         *      当分享人是团长，分销员，客户时，客户等级为分享人的下一等级
         *      客户下单时，需要判断下单人是否有团队id，有团队id各级分销，没有则省长获得所有
         *      当在后台修改团长的团队id时，所有下级的团队id会随之一同修改，客户下单 团长获得佣金
         *  合伙人二维码：
         *      同商品二维码
         *  团码：
         *      团长进团，其他人扫码无效
         */
        switch (qrcode_type) {
            case "0": // 商品详情
            case "1": // 招募合伙人
                // 判断邀请人用户等级,
                if (recommendUser != null && recommendUser.getMember_type() != 3) {
                    // 修改用户级别
                    int member_type = recommendUser.getMember_type() - 1 < 0 ? 0 : recommendUser.getMember_type() - 1;
                    user.setMember_type(member_type);
                }
                if (StringUtil.isBlank(user.getTeam_id()) && !StringUtil.isBlank(team_id)) {
                    setTeam(team_id, user);
                }
                break;
            case "2": // 团码
                // 判断当前用户是否为团长
                if (user.getMember_type() == 2) {
                    setTeam(team_id, user);
                }
                break;
            default:
                break;
        }
    }

    /**
     * 设置用户的团队信息
     *
     * @param team_id 团队id
     * @param user    用户信息
     */
    private void setTeam(String team_id, AppUserApiEntity user) {
        String team_s = teamApiRepository.teamDtail(WXConfig.COMPANYID, Filters.eq("team_id", team_id));
        if (StringUtil.isBlank(team_s)) return;
        TeamApiEntityDTO dto = new Gson().fromJson(team_s, TeamApiEntityDTO.class);
        user.setTeam_id(dto.getTeam_id());
        user.setTeam_name(dto.getTeam_name());
    }
}
